package lb

import (
	"math/rand"
	"sync/atomic"
)

//简单轮询负载均衡器
type RoundRobin struct {
	counter uint32 //计数器
}

func (r *RoundRobin) Next(key string, hosts []*HostInstance) *HostInstance {
	//自增
	count := atomic.AddUint32(&r.counter, 1)
	//取模计算索引
	index := int(count) % len(hosts)
	//按索引取出实例
	instance := hosts[index]
	return instance
}

//随机算法

type RandomBalancer struct {
}

func (r *RandomBalancer) Next(key string, hosts []*HostInstance) *HostInstance {
	//随机
	count := rand.Int31()
	//取模计算索引
	index := int(count) % len(hosts)
	//按索引取出实例
	instance := hosts[index]
	return instance
}

//简单轮询负载均衡器
type WeightedRoundRobin struct {
	counter uint32 //计数器
}

func (r *WeightedRoundRobin) Next(key string, hosts []*HostInstance) *HostInstance {
	if len(hosts) == 0 {
		return nil
	}

	//计算总权重
	totalWeight := int32(0)
	for _, h := range hosts {
		totalWeight += h.EffectWeight
	}
	//自增
	count := atomic.AddUint32(&r.counter, 1)
	//取模计算索引
	index := int(count) % len(hosts)
	//按索引取出实例
	instance := hosts[index]
	return instance
}

func (r *WeightedRoundRobin) Next2(key string, hosts []*HostInstance) *HostInstance {
	if len(hosts) == 0 {
		return nil
	}
	selected := hosts[0]
	totalWeight := int32(0)
	for i := 0; i < len(hosts); i++ {
		//hosts[i].init()
		totalWeight = totalWeight + hosts[i].EffectWeight
		hosts[i].CurrentWeight = hosts[i].CurrentWeight + hosts[i].EffectWeight
		if hosts[i].CurrentWeight > selected.CurrentWeight {
			selected = hosts[i]
		}
	}
	selected.CurrentWeight = selected.CurrentWeight - totalWeight
	return selected
}
